package com.telit.firecommand.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaolyuh.annotation.CacheEvict;
import com.telit.common.dto.DistrictDTO;
import com.telit.common.entity.PageData;
import com.telit.common.exception.ForestBaseException;
import com.telit.common.util.JwtTokenUtils;
import com.telit.common.util.MediaUrlUtils;
import com.telit.common.util.RedisUtils;
import com.telit.firecommand.constant.FireConstant;
import com.telit.firecommand.constant.RedisKeyConstant;
import com.telit.firecommand.dao.CommCameraInfoDao;
import com.telit.firecommand.dao.CommFireAlarmDao;
import com.telit.firecommand.dao.FireCameraDAO;
import com.telit.firecommand.dao.GeoXzqhCunDao;
import com.telit.firecommand.dto.CameraFirePointDTO;
import com.telit.firecommand.dto.DistrictCountDTO;
import com.telit.firecommand.dto.ThermalImagingInfoDTO;
import com.telit.firecommand.dto.VisibleLightInfoDTO;
import com.telit.firecommand.entity.CommCameraInfo;
import com.telit.firecommand.entity.CommFireAlarm;
import com.telit.firecommand.entity.GeoXzqhCun;
import com.telit.firecommand.model.camera.QryDistrictListByCodesRequest;
import com.telit.firecommand.service.CameraInfoService;
import com.telit.firecommand.service.DistrictService;
import com.telit.firecommand.vo.CameraVO;
import com.telit.firecommand.vo.FirePointResourceVO;
import com.telit.firecommand.vo.SaidaDistrictTreeVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


/**
 * 监控设备信息
 *
 * @author yuezhuang
 * @date 2022-08-30
 */
@Service
public class CameraInfoServiceImpl implements CameraInfoService {

    @Autowired
    private DistrictService districtService;

    @Autowired
    private FireCameraDAO fireCameraDAO;

    @Autowired
    private CommCameraInfoDao commCameraInfoDAO;

    @Autowired
    private GeoXzqhCunDao geoXzqhCunDao;

    @Autowired
    private CommFireAlarmDao commFireAlarmDao;

    @Override
    @CacheEvict(value = {"firecommand:camera:findById", "firecommand:camera:searchSimpleList",
            "firecommand:camera:selectCount", "firecommand:camera:queryByMonitoringType",
            "firecommand:monitoring:count", "firecommand:camera:queryListByPoint",
            "firecommand:camera:querySimpleByCondition"}, allEntries = true)
    public void addCamera(CommCameraInfo commonCameraInfo) {
        commonCameraInfo.setCreateTime(new Date());
        String name = JwtTokenUtils.getRealName();
        commonCameraInfo.setCreatePerson(name);
        //可见光
        VisibleLightInfoDTO visibleLightInfoDTO = commonCameraInfo.getVisibleLightInfoDTO();
        //热成像
        ThermalImagingInfoDTO thermalImagingInfoDTO = commonCameraInfo.getThermalImagingInfoDTO();
        if (visibleLightInfoDTO != null && visibleLightInfoDTO.getIp() != null && !"".equals(
                visibleLightInfoDTO.getIp())) {
            commonCameraInfo.setPictureType(0);
            BeanUtils.copyProperties(visibleLightInfoDTO, commonCameraInfo);
            commCameraInfoDAO.insertSelective(commonCameraInfo);
        }
        if (thermalImagingInfoDTO != null && thermalImagingInfoDTO.getIp() != null && !"".equals(
                thermalImagingInfoDTO.getIp())) {
            commonCameraInfo.setPictureType(1);
            BeanUtils.copyProperties(thermalImagingInfoDTO, commonCameraInfo);
            commCameraInfoDAO.insertSelective(commonCameraInfo);
        }

    }

    @Override
    @CacheEvict(value = {"firecommand:camera:findById", "firecommand:camera:searchSimpleList",
            "firecommand:camera:selectCount", "firecommand:camera:queryByMonitoringType",
            "firecommand:monitoring:count", "firecommand:camera:queryListByPoint",
            "firecommand:camera:querySimpleByCondition"}, allEntries = true)
    public void deleteById(List<Long> ids) {
        for (Long id : ids) {
            commCameraInfoDAO.deleteByPrimaryKey(id);
        }
    }

    @Override
    @CacheEvict(value = {"firecommand:camera:findById", "firecommand:camera:searchSimpleList",
            "firecommand:camera:queryByMonitoringType", "firecommand:monitoring:count",
            "firecommand:camera:queryListByPoint", "firecommand:camera:querySimpleByCondition"}, allEntries = true)
    public void updateById(CommCameraInfo commonCameraInfo) {
        commonCameraInfo.setCreateTime(new Date());
        String name = JwtTokenUtils.getRealName();
        commonCameraInfo.setCreatePerson(name);
        VisibleLightInfoDTO visibleLightInfoDTO = commonCameraInfo.getVisibleLightInfoDTO();
        ThermalImagingInfoDTO thermalImagingInfoDTO = commonCameraInfo.getThermalImagingInfoDTO();
        //编辑视频监控时判断当前所属行政区划，和入库行政区划是否一致，不一致重新设置行政区划名称
        CommCameraInfo retCommCameraInfo = commCameraInfoDAO.selectByPrimaryKey(commonCameraInfo.getId());
        if (!StrUtil.equals(retCommCameraInfo.getDistrictCode(), commonCameraInfo.getDistrictCode())) {
            DistrictDTO districtDTO = districtService.qryDistrictInfo(commonCameraInfo.getDistrictCode());
            String cameraDistrictName = districtDTO.getName();
            commonCameraInfo.setDistrictName(cameraDistrictName);
        }

        if (visibleLightInfoDTO != null && visibleLightInfoDTO.getIp() != null && !"".equals(
                visibleLightInfoDTO.getIp())) {
            commonCameraInfo.setPictureType(0);
            BeanUtils.copyProperties(visibleLightInfoDTO, commonCameraInfo);
            commCameraInfoDAO.updateByNameAndType(commonCameraInfo);
        }
        if (thermalImagingInfoDTO != null && thermalImagingInfoDTO.getIp() != null && !"".equals(
                thermalImagingInfoDTO.getIp())) {
            commonCameraInfo.setPictureType(1);
            BeanUtils.copyProperties(thermalImagingInfoDTO, commonCameraInfo);
            commCameraInfoDAO.updateByNameAndType(commonCameraInfo);
        }
        commCameraInfoDAO.updateByPrimaryKeySelective(commonCameraInfo);
    }

    @Override
    public CommCameraInfo queryById(Long id) {
        CommCameraInfo commCameraInfo = commCameraInfoDAO.selectByPrimaryKey(id);
        String documentation = commCameraInfo.getDocumentation();
        List<String> fileUrl = MediaUrlUtils.handleMediaUrlToList(documentation);
        commCameraInfo.setFileUrl(fileUrl);
        VisibleLightInfoDTO visibleLightInfoDTO = new VisibleLightInfoDTO();
        ThermalImagingInfoDTO thermalImagingInfoDTO = new ThermalImagingInfoDTO();

        CommCameraInfo visibleLightInfo = commCameraInfoDAO.queryByNameAndType(commCameraInfo.getName(),
                commCameraInfo.getMonitoringType(), 0, null, commCameraInfo.getDistrictCode());
        CommCameraInfo thermalImagingInfo = commCameraInfoDAO.queryByNameAndType(commCameraInfo.getName(),
                commCameraInfo.getMonitoringType(), 1, null, commCameraInfo.getDistrictCode());
        if (visibleLightInfo != null) {
            BeanUtils.copyProperties(visibleLightInfo, visibleLightInfoDTO);
        }
        if (thermalImagingInfo != null) {
            BeanUtils.copyProperties(thermalImagingInfo, thermalImagingInfoDTO);
        }
        commCameraInfo.setThermalImagingInfoDTO(thermalImagingInfoDTO);
        commCameraInfo.setVisibleLightInfoDTO(visibleLightInfoDTO);
        return commCameraInfo;
    }

    /**
     * 首页获取监控列表
     *
     * @param districtCode 行政区划
     *
     * @return 监控列表
     */
    @Override
    public List<CameraVO> getCameraPosition(String districtCode) {
        List<CameraVO> currentList = new ArrayList<>();
        String cameraInfos = RedisUtils.get(RedisKeyConstant.CAMERA_POSITION + districtCode);
        if (cameraInfos == null) {
            //查询监控列表
            LambdaQueryWrapper<CommCameraInfo> commCameraInfoQueryWrapper = new LambdaQueryWrapper<>();
            commCameraInfoQueryWrapper.eq(CommCameraInfo::getPictureType, 0);
            commCameraInfoQueryWrapper.likeRight(CommCameraInfo::getDistrictCode, districtCode);
            commCameraInfoQueryWrapper.last("limit 4");
            List<CommCameraInfo> commCameraInfos = commCameraInfoDAO.selectList(commCameraInfoQueryWrapper);
            List<CameraVO> finalCurrentList = currentList;
            commCameraInfos.forEach(commCameraInfo -> {
                finalCurrentList.add(CameraVO.builder()
                        .areaCode(commCameraInfo.getDistrictCode())
                        .areaName(commCameraInfo.getDistrictName())
                        .cameraId(commCameraInfo.getCameraIndexCode())  //可见光、热成像
                        .cameraName(commCameraInfo.getName())
                        .cameraRadius(StringUtils.isNotEmpty(commCameraInfo.getMonitoringRadius()) ? new BigDecimal(
                                commCameraInfo.getMonitoringRadius()) : null)
                        .cameraType(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                                commCameraInfo.getMonitoringType()) : null)
                        .code(commCameraInfo.getCameraIndexCode())
                        .id(commCameraInfo.getId())
                        .frameType(commCameraInfo.getPictureType())
                        .isControl(commCameraInfo.getEnableController())
                        .latitude(commCameraInfo.getLatitude())
                        .longitude(commCameraInfo.getLongitude())
                        .online(StringUtils.isNotEmpty(commCameraInfo.getDeviceStatus()) ? Integer.parseInt(
                                commCameraInfo.getDeviceStatus()) : null)
                        .placeName(commCameraInfo.getAddress())
//                            .previewUrl()
                        .type(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                                commCameraInfo.getMonitoringType()) : null)
                        .equipmentType(StringUtils.isNotEmpty(commCameraInfo.getDeviceType()) ? Integer.parseInt(
                                commCameraInfo.getDeviceType()) : null)
                        .token(commCameraInfo.getToken())
                        .build());
            });
            currentList = finalCurrentList;
        } else {
            currentList = JSONObject.parseArray(cameraInfos, CameraVO.class);
        }
        return currentList;
    }

    /**
     * 根据父行政区划编码查询子类集合
     * <p>
     * 监控挂在区、县下面，所以区县是叶子节点了。行政区划编码长度是6
     * </p>
     *
     * @param type         监控类型 1防火监控2防盗监控3卡口监控
     * @param online       在线  1在线 0离线
     * @param cameraName   监控名称（模糊查询）
     * @param districtCode 父行政区划编码
     *
     * @return DistrictCountDTO Obj
     */
    @Override
    public DistrictCountDTO qryDistrictListByParentCode(Integer type, Integer online, String cameraName,
                                                        String districtCode) {
        if (districtCode.length() > FireConstant.DISTRICT_TOWN_CODE_LENGTH) {//乡镇
            throw new ForestBaseException("非法参数！");
        }

        //当前行政区划信息
//        DistrictDTO current = districtService.qryDistrictInfo(districtCode);
        String shengCode = null;
        String shiCode = null;
        String xianCode = null;
        String xiangCode = null;
        String cunCode = null;
        int childCodeLength = 0;//子行政区划长度
        String groupByName = null;//查询子行政区划，分组的字段
        int districtCodeLength = districtCode.length();
        if (districtCodeLength == 2) {
            shengCode = districtCode;
            groupByName = "sheng,sheng_name,shi,shi_name";
            childCodeLength = 4;
        } else if (districtCodeLength == 4) {
            shiCode = districtCode;
            groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name";
            childCodeLength = 6;
        } else if (districtCodeLength == 6) {
            xianCode = districtCode;
            groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name";
            childCodeLength = 9;
        } else if (districtCodeLength == 9) {
            xiangCode = districtCode;
            groupByName = "sheng,sheng_name,shi,shi_name,xian,xian_name,xiang,xiang_name,cun,cun_name";
        } else {
            cunCode = districtCode;
        }
        GeoXzqhCun geoXzqhCun = geoXzqhCunDao.selectByCondition(shengCode, shiCode, xianCode, xiangCode, cunCode);
        if (geoXzqhCun == null) {
            throw new ForestBaseException("未查询到该行政区划，请稍后再试！");
        }
        //行政区划名称
        String districtName = null;
        if (districtCodeLength == 2) {
            districtName = geoXzqhCun.getShengName();
        } else if (districtCodeLength == 4) {
            districtName = geoXzqhCun.getShiName();
        } else if (districtCodeLength == 6) {
            districtName = geoXzqhCun.getXianName();
        } else if (districtCodeLength == 9) {
            districtName = geoXzqhCun.getXiangName();
        } else {
            districtName = geoXzqhCun.getCunName();
        }
        DistrictDTO current = DistrictDTO.builder()
                .id(null)
                .code(districtCode)
                .name(districtName)
                .parentCode(null)
                .build();

        //查询当前行政区划的监控列表（非乡镇，不查询当前行政区划的监控列表）
        List<CameraVO> currentList = new ArrayList<>();
        if (districtCode.length() == FireConstant.DISTRICT_TOWN_CODE_LENGTH) {
            //查询监控列表
            LambdaQueryWrapper<CommCameraInfo> commCameraInfoQueryWrapper = new LambdaQueryWrapper<>();
            commCameraInfoQueryWrapper.eq(CommCameraInfo::getPictureType, 0);
            if (type != null) {
                commCameraInfoQueryWrapper.eq(CommCameraInfo::getMonitoringType, String.valueOf(type));
            }
            if (online != null) {
                commCameraInfoQueryWrapper.eq(CommCameraInfo::getDeviceStatus, String.valueOf(online));
            }
            if (StringUtils.isNotEmpty(cameraName)) {
                commCameraInfoQueryWrapper.like(CommCameraInfo::getName, cameraName);
            }
            if (StringUtils.isNotEmpty(districtCode)) {
                commCameraInfoQueryWrapper.likeRight(CommCameraInfo::getDistrictCode, districtCode);
            }
            List<CommCameraInfo> commCameraInfos = commCameraInfoDAO.selectList(commCameraInfoQueryWrapper);
            if (!CollectionUtils.isEmpty(commCameraInfos)) {
                List<CameraVO> finalCurrentList = currentList;
                commCameraInfos.forEach(commCameraInfo -> {
                    finalCurrentList.add(CameraVO.builder()
                            .areaCode(commCameraInfo.getDistrictCode())
                            .areaName(commCameraInfo.getDistrictName())
                            .cameraId(commCameraInfo.getCameraIndexCode())  //可见光、热成像
                            .cameraName(commCameraInfo.getName())
                            .cameraRadius(StringUtils.isNotEmpty(commCameraInfo.getMonitoringRadius()) ? new BigDecimal(
                                    commCameraInfo.getMonitoringRadius()) : null)
                            .cameraType(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                                    commCameraInfo.getMonitoringType()) : null)
                            .code(commCameraInfo.getCameraIndexCode())
                            .id(commCameraInfo.getId())
                            .frameType(commCameraInfo.getPictureType())
                            .isControl(commCameraInfo.getEnableController())
                            .latitude(commCameraInfo.getLatitude())
                            .longitude(commCameraInfo.getLongitude())
                            .online(StringUtils.isNotEmpty(commCameraInfo.getDeviceStatus()) ? Integer.parseInt(
                                    commCameraInfo.getDeviceStatus()) : null)
                            .placeName(commCameraInfo.getAddress())
//                            .previewUrl()
                            .type(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                                    commCameraInfo.getMonitoringType()) : null)
                            .equipmentType(StringUtils.isNotEmpty(commCameraInfo.getDeviceType()) ? Integer.parseInt(
                                    commCameraInfo.getDeviceType()) : null)
                            .token(commCameraInfo.getToken())
                            .build());
                });
                currentList = finalCurrentList;
            }
        }

        //查询当前行政区划监控数量
        LambdaQueryWrapper<CommCameraInfo> commCameraInfoQueryWrapper = new LambdaQueryWrapper<>();
        commCameraInfoQueryWrapper.eq(CommCameraInfo::getPictureType, 0);
        if (type != null) {
            commCameraInfoQueryWrapper.eq(CommCameraInfo::getMonitoringType, String.valueOf(type));
        }
        if (online != null) {
            commCameraInfoQueryWrapper.eq(CommCameraInfo::getDeviceStatus, String.valueOf(online));
        }
        if (StringUtils.isNotEmpty(cameraName)) {
            commCameraInfoQueryWrapper.like(CommCameraInfo::getName, cameraName);
        }
        if (StringUtils.isNotEmpty(districtCode)) {
            commCameraInfoQueryWrapper.likeRight(CommCameraInfo::getDistrictCode, districtCode);
        }
        Integer currentCount = commCameraInfoDAO.selectCount(commCameraInfoQueryWrapper);

        //构建返回DTO
        DistrictCountDTO districtCountDTO = DistrictCountDTO.builder()
                .id(current.getId())
                .name(current.getName())
                .code(current.getCode())
                .parentCode(current.getParentCode())
                .rank(current.getRank())
                .count(currentCount)
                .cameraList(currentList)
                .build();
        if (districtCode.length() == FireConstant.DISTRICT_TOWN_CODE_LENGTH) {//县区直接返回，不构建子行政区划
            return districtCountDTO;
        }

        List<DistrictCountDTO> countChildren = new ArrayList<>();
        //子类行政区划集合
//        List<DistrictDTO> children = districtService.qryListByParentCode(districtCode);
        List<DistrictDTO> children = new ArrayList<>();
        List<GeoXzqhCun> geoXzqhCuns = geoXzqhCunDao.selectByParentCode(shengCode, shiCode, xianCode, xiangCode,
                cunCode, groupByName, null, null);
        if (!CollectionUtils.isEmpty(geoXzqhCuns)) {
            int finalChildCodeLength = childCodeLength;
            geoXzqhCuns.forEach(cun -> {
                String childName = null;
                String childCode = null;
                if (finalChildCodeLength == 4) {
                    childName = cun.getShiName();
                    childCode = cun.getShi();
                } else if (finalChildCodeLength == 6) {
                    childName = cun.getXianName();
                    childCode = cun.getXian();
                } else if (finalChildCodeLength == 9) {
                    childName = cun.getXiangName();
                    childCode = cun.getXiang();
                } else {
                    childName = cun.getCunName();
                    childCode = cun.getCun();
                }
                children.add(DistrictDTO.builder()
                        .id(null)
                        .code(childCode)
                        .name(childName)
                        .parentCode(null)
                        .build());
            });
        }

        children.forEach(districtDTO -> {
            //查询监控列表
            LambdaQueryWrapper<CommCameraInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(CommCameraInfo::getPictureType, 0);
            if (type != null) {
                lambdaQueryWrapper.eq(CommCameraInfo::getMonitoringType, String.valueOf(type));
            }
            if (online != null) {
                lambdaQueryWrapper.eq(CommCameraInfo::getDeviceStatus, String.valueOf(online));
            }
            if (StringUtils.isNotEmpty(cameraName)) {
                lambdaQueryWrapper.like(CommCameraInfo::getName, cameraName);
            }
            if (StringUtils.isNotEmpty(districtDTO.getCode())) {
                lambdaQueryWrapper.likeRight(CommCameraInfo::getDistrictCode, districtDTO.getCode());
            }
            List<CommCameraInfo> commCameraInfos = commCameraInfoDAO.selectList(lambdaQueryWrapper);
            List<CameraVO> childList = new ArrayList<>();
            Integer childCount = 0;
            if (!CollectionUtils.isEmpty(commCameraInfos)) {
                childCount = commCameraInfos.size();
                List<CameraVO> finalCurrentList = childList;
                commCameraInfos.forEach(commCameraInfo -> {
                    finalCurrentList.add(CameraVO.builder()
                            .areaCode(commCameraInfo.getDistrictCode())
                            .areaName(commCameraInfo.getDistrictName())
                            .cameraId(commCameraInfo.getCameraIndexCode())  //可见光、热成像
                            .cameraName(commCameraInfo.getName())
                            .cameraRadius(StringUtils.isNotEmpty(commCameraInfo.getMonitoringRadius()) ? new BigDecimal(
                                    commCameraInfo.getMonitoringRadius()) : null)
                            .cameraType(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                                    commCameraInfo.getMonitoringType()) : null)
                            .code(commCameraInfo.getCameraIndexCode())
                            .id(commCameraInfo.getId())
                            .frameType(commCameraInfo.getPictureType())
                            .isControl(commCameraInfo.getEnableController())
                            .latitude(commCameraInfo.getLatitude())
                            .longitude(commCameraInfo.getLongitude())
                            .online(StringUtils.isNotEmpty(commCameraInfo.getDeviceStatus()) ? Integer.parseInt(
                                    commCameraInfo.getDeviceStatus()) : null)
                            .placeName(commCameraInfo.getAddress())
//                            .previewUrl()
                            .type(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                                    commCameraInfo.getMonitoringType()) : null)
                            .equipmentType(StringUtils.isNotEmpty(commCameraInfo.getDeviceType()) ? Integer.parseInt(
                                    commCameraInfo.getDeviceType()) : null)
                            .token(commCameraInfo.getToken())
                            .build());
                });
                childList = finalCurrentList;
            }

            DistrictCountDTO countDTO = DistrictCountDTO.builder()
                    .id(districtDTO.getId())
                    .name(districtDTO.getName())
                    .code(districtDTO.getCode())
                    .parentCode(districtDTO.getParentCode())
                    .rank(districtDTO.getRank())
                    .count(childCount)
                    .cameraList(childList)
                    .build();

            countChildren.add(countDTO);
        });

        districtCountDTO.setChildren(countChildren);
        return districtCountDTO;
    }

    /**
     * 根据行政区划编码批量查询
     *
     * @param qryDistrictListByCodesRequest qryDistrictListByCodesRequest
     *
     * @return 行政区划+数量+监控列表
     */
    @Override
    public DistrictCountDTO qryDistrictListByCodes(QryDistrictListByCodesRequest qryDistrictListByCodesRequest) {
        if (qryDistrictListByCodesRequest.getDistrictCode().length() > FireConstant.DISTRICT_TOWN_CODE_LENGTH) {//县区
            throw new ForestBaseException("非法参数！");
        }
        qryDistrictListByCodesRequest.validateAndThrow();

        //调用赛达接口，查询当前parentCode下所有的行政区划、监控信息
        //只根据当前用户所属行政区划查询一次 避免循环调用
        //监控挂在区、县下面，所以区县是叶子节点了。行政区划编码长度是6，后面的子行政区划直接丢弃
//        DataReturn dataReturn = alarmsFeignClient.qryCameraTree(qryDistrictListByCodesRequest.getDistrictCode(), null,
//                null, null);
//        if (!ResultCode.SUCCESS.getCode().equals(dataReturn.getCode())
//                && !FireConstant.ALARMS_SUCCESS_CODE.equals(dataReturn.getCode())) {
//            throw new ForestBaseException(dataReturn.getErrorMsg());
//        }
        List<SaidaDistrictTreeVO> trees = areaTree(qryDistrictListByCodesRequest.getDistrictCode(),
                qryDistrictListByCodesRequest.getType(), qryDistrictListByCodesRequest.getOnline(),
                qryDistrictListByCodesRequest.getCameraName());
        //赛达当前区域下的 行政区域和监控列表
        SaidaDistrictTreeVO currentVO = trees.get(0);
        //格式化后的数据
        DistrictCountDTO districtCountDTO = formatSaidaData(currentVO);

        //判断当前节点是否需要被返回，如果不需要返回的话，则返回null（顶级节点必须返回）
        districtCountDTO = isHit(districtCountDTO, qryDistrictListByCodesRequest.getDistrictCodeList(),
                qryDistrictListByCodesRequest.getCameraIdList());

        //计算在线监控
        long onlineNum = countOnlineNum(Collections.singletonList(districtCountDTO));
        districtCountDTO.setOnlineCount((int) onlineNum);

        //计算当前行政区划数量（批量查询时可能当前行政区划下面只选择了部分区域或者部分监控）
        countNum(districtCountDTO);

        return districtCountDTO;
    }

    public List<SaidaDistrictTreeVO> areaTree(String areaCode, String type, String online, String cameraName) {
        List<SaidaDistrictTreeVO> saidaDistrictTreeVOS = fireCameraDAO.areaTree(areaCode, type, online, cameraName);
        return buildTree(saidaDistrictTreeVOS);
    }

    public List<SaidaDistrictTreeVO> buildTree(List<SaidaDistrictTreeVO> list) {
        Map<String, SaidaDistrictTreeVO> map = new HashMap<>();
        List<SaidaDistrictTreeVO> trees = new ArrayList<>();
        list.forEach(saidaDistrictTreeVO -> {
            map.put(saidaDistrictTreeVO.getCode(), saidaDistrictTreeVO);
        });

        list.forEach(saidaDistrictTreeVO -> {
            SaidaDistrictTreeVO parent = map.get(saidaDistrictTreeVO.getParentCode());
            if (parent != null) {
                List<SaidaDistrictTreeVO> children = parent.getChildren();
                if (children == null) {
                    children = new ArrayList<>();
                }
                children.add(saidaDistrictTreeVO);
                parent.setChildren(children);
            } else {
                trees.add(saidaDistrictTreeVO);
            }
        });
        return trees;
    }

    /**
     * 根据火点信息查询实时视频
     *
     * @param districtCode 行政区划编码
     * @param fireId       火情id
     * @param firePoint    point(经纬+纬度)
     *
     * @return 监控集合
     */
    @Deprecated
    @Override
    public List<CameraVO> qryCameraListByPoint(String districtCode, String fireId, String firePoint) {
        //查询缓存
        String rtv = RedisUtils.get(RedisKeyConstant.RTV + fireId + ":" + districtCode);
        if (StringUtils.isNotEmpty(rtv)) {
            return Arrays.asList(JSON.parseObject(rtv, CameraVO.class));
        }

        List<CommCameraInfo> commCameraInfoList = fireCameraDAO.qryCameraListByPoint(districtCode, firePoint, null,
                null, null);
        List<CameraVO> cameraVOList = new ArrayList<>();
        commCameraInfoList.forEach(commCameraInfo -> {
            cameraVOList.add(CameraVO.builder()
                    .areaCode(commCameraInfo.getDistrictCode())
                    .areaName(commCameraInfo.getDistrictName())
                    .cameraId(commCameraInfo.getCameraIndexCode())  //可见光、热成像
                    .cameraName(commCameraInfo.getName())
                    .cameraRadius(StringUtils.isNotEmpty(commCameraInfo.getMonitoringRadius()) ? new BigDecimal(
                            commCameraInfo.getMonitoringRadius()) : null)
                    .cameraType(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                            commCameraInfo.getMonitoringType()) : null)
                    .code(commCameraInfo.getCameraIndexCode())
                    .id(commCameraInfo.getId())
                    .frameType(commCameraInfo.getPictureType())
                    .isControl(commCameraInfo.getEnableController())
                    .latitude(commCameraInfo.getLatitude())
                    .longitude(commCameraInfo.getLongitude())
                    .online(StringUtils.isNotEmpty(commCameraInfo.getDeviceStatus()) ? Integer.parseInt(
                            commCameraInfo.getDeviceStatus()) : null)
                    .placeName(commCameraInfo.getAddress())
//                            .previewUrl()
                    .type(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                            commCameraInfo.getMonitoringType()) : null)
                    .equipmentType(StringUtils.isNotEmpty(commCameraInfo.getDeviceType()) ? Integer.parseInt(
                            commCameraInfo.getDeviceType()) : null)
                    .token(commCameraInfo.getToken())
                    .build());
        });

        //TODO：加入fire_site表后，需要修改处理逻辑，fire_camera中多个监控（可见光、热成像）对应一个fire_site
        //TODO：需要 在 CameraVO 中返回 热成像id 和 可见光id

        return cameraVOList;
    }

    /**
     * 根据火点信息查询资源
     *
     * @param districtCode 行政区划编码
     * @param firePoint    point(经纬+纬度)
     * @param keyWords     搜索关键字
     *
     * @return FirePointResourceVO
     */
    @Override
    public FirePointResourceVO qryResourceListByPoint(String districtCode, String firePoint, String keyWords) {
        List<CommCameraInfo> commCameraInfoList = fireCameraDAO.qryCameraListByPoint(districtCode, firePoint, keyWords,
                null, null);
        List<CameraVO> cameraVOList = new ArrayList<>();
        commCameraInfoList.forEach(commCameraInfo -> {
            cameraVOList.add(CameraVO.builder()
                    .areaCode(commCameraInfo.getDistrictCode())
                    .areaName(commCameraInfo.getDistrictName())
                    .cameraId(commCameraInfo.getCameraIndexCode())  //可见光、热成像
                    .cameraName(commCameraInfo.getName())
                    .cameraRadius(StringUtils.isNotEmpty(commCameraInfo.getMonitoringRadius()) ? new BigDecimal(
                            commCameraInfo.getMonitoringRadius()) : null)
                    .cameraType(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                            commCameraInfo.getMonitoringType()) : null)
                    .code(commCameraInfo.getCameraIndexCode())
                    .id(commCameraInfo.getId())
                    .frameType(commCameraInfo.getPictureType())
                    .isControl(commCameraInfo.getEnableController())
                    .latitude(commCameraInfo.getLatitude())
                    .longitude(commCameraInfo.getLongitude())
                    .online(StringUtils.isNotEmpty(commCameraInfo.getDeviceStatus()) ? Integer.parseInt(
                            commCameraInfo.getDeviceStatus()) : null)
                    .placeName(commCameraInfo.getAddress())
//                            .previewUrl()
                    .type(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                            commCameraInfo.getMonitoringType()) : null)
                    .equipmentType(StringUtils.isNotEmpty(commCameraInfo.getDeviceType()) ? Integer.parseInt(
                            commCameraInfo.getDeviceType()) : null)
                    .token(commCameraInfo.getToken())
                    .build());
        });

        //无人机：在飞行、火点经纬度+无人机经纬度计算距离 5 公里以内
//        List<UavVO> uavList = fireCameraDAO.qryUavListByPoint();
        return FirePointResourceVO.builder()
                .cameraList(cameraVOList)
                .build();
    }

    /**
     * 缓存火场态势首页实时视频
     *
     * @param districtCode 行政区划编码
     * @param fireId       火情id
     * @param cameraVO     监控信息
     */
    @Deprecated
    @Override
    public void cacheCameraByPoint(String districtCode, String fireId, CameraVO cameraVO) {
        RedisUtils.set(RedisKeyConstant.RTV + fireId + ":" + districtCode, JSON.toJSONString(cameraVO));
    }

    /**
     * 缓存火场态势首页资源
     *
     * @param districtCode        行政区划编码
     * @param fireId              火情id
     * @param firePointResourceVO 资源信息
     */
    @Override
    public void cacheResourceByPoint(String districtCode, String fireId, FirePointResourceVO firePointResourceVO) {
        RedisUtils.set(RedisKeyConstant.RTV + fireId + ":" + districtCode, JSON.toJSONString(firePointResourceVO));
    }

    /**
     * 根据火点信息查询缓存资源
     *
     * @param districtCode 行政区划编码
     * @param fireId       火情id
     * @param firePoint    point(经纬+纬度)
     *
     * @return FirePointResourceVO
     */
    @Override
    public FirePointResourceVO qryCacheResourceByPoint(String districtCode, String fireId, String firePoint) {
        //查询缓存
        String rtv = RedisUtils.get(RedisKeyConstant.RTV + fireId + ":" + districtCode);
        if (StringUtils.isNotEmpty(rtv)) {
            return JSON.parseObject(rtv, FirePointResourceVO.class);
        }

        //将 + 转成 空格
        firePoint = firePoint.replace("+", " ");
        //视频监控
        List<CommCameraInfo> commCameraInfoList = fireCameraDAO.qryCameraListByPoint(districtCode, firePoint, null, 0,
                null);
        List<CameraVO> cameraVOList = new ArrayList<>();
        commCameraInfoList.forEach(commCameraInfo -> {
            cameraVOList.add(CameraVO.builder()
                    .areaCode(commCameraInfo.getDistrictCode())
                    .areaName(commCameraInfo.getDistrictName())
                    .cameraId(commCameraInfo.getCameraIndexCode())  //可见光、热成像
                    .cameraName(commCameraInfo.getName())
                    .cameraRadius(StringUtils.isNotEmpty(commCameraInfo.getMonitoringRadius()) ? new BigDecimal(
                            commCameraInfo.getMonitoringRadius()) : null)
                    .cameraType(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                            commCameraInfo.getMonitoringType()) : null)
                    .code(commCameraInfo.getCameraIndexCode())
                    .id(commCameraInfo.getId())
                    .frameType(commCameraInfo.getPictureType())
                    .isControl(commCameraInfo.getEnableController())
                    .latitude(commCameraInfo.getLatitude())
                    .longitude(commCameraInfo.getLongitude())
                    .online(StringUtils.isNotEmpty(commCameraInfo.getDeviceStatus()) ? Integer.parseInt(
                            commCameraInfo.getDeviceStatus()) : null)
                    .placeName(commCameraInfo.getAddress())
//                            .previewUrl()
                    .type(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                            commCameraInfo.getMonitoringType()) : null)
                    .equipmentType(StringUtils.isNotEmpty(commCameraInfo.getDeviceType()) ? Integer.parseInt(
                            commCameraInfo.getDeviceType()) : null)
                    .token(commCameraInfo.getToken())
                    .build());
        });

        //无人机

        return FirePointResourceVO.builder().cameraList(cameraVOList).build();
    }

    /**
     * 批量查询时可能当前行政区划下面只选择了部分区域或者部分监控，需要重新计算监控数量。
     *
     * @param districtCountDTO 顶级行政区划
     */
    public void countNum(DistrictCountDTO districtCountDTO) {
        countNum(districtCountDTO.getChildren());
        long num = districtCountDTO.getChildren()
                .stream()
                .mapToLong(DistrictCountDTO::getCount).sum();
        districtCountDTO.setCount((int) num);
    }

    /**
     * 批量查询时可能当前行政区划下面只选择了部分区域或者部分监控，需要重新计算监控数量。
     *
     * @param list 子行政区划
     */
    public void countNum(List<DistrictCountDTO> list) {
        list.forEach(districtCountDTO -> {
            if (CollectionUtils.isEmpty(districtCountDTO.getChildren())) {
                //市区级，计算监控数量
                districtCountDTO.setCount(districtCountDTO.getCameraList().size());
            } else {
                //否则计算子区域监控数量
                countNum(districtCountDTO.getChildren());
                long num = districtCountDTO.getChildren()
                        .stream()
                        .mapToLong(DistrictCountDTO::getCount).sum();
                districtCountDTO.setCount((int) num);
            }
        });
    }

    /**
     * 计算在线数量
     *
     * @param list 行政区划集合
     *
     * @return 在线数量
     */
    public long countOnlineNum(List<DistrictCountDTO> list) {
        AtomicReference<Long> num = new AtomicReference<>((long) 0);
        list.forEach(districtCountDTO -> {
            //当前行政区划在线数量
            long n = districtCountDTO.getCameraList().stream()
                    .filter(cameraVO -> cameraVO.getOnline() == 1)
                    .count();
            num.updateAndGet(v -> v + n);

            //子类在线数量
            long cn = countOnlineNum(districtCountDTO.getChildren());
            num.updateAndGet(v -> v + cn);
        });

        return num.get();
    }

    /**
     * 判断当前节点是否需要被返回，如果不需要返回的话，则返回null
     * 顶级节点必须返回
     *
     * @param districtCountDTO 当前节点
     * @param districtCodeList 待查询的行政区划code列表
     * @param cameraIdList     待查询的监控id列表
     *
     * @return 节点是否需要被返回，如果不需要返回的话，则返回null
     */
    public DistrictCountDTO isHit(DistrictCountDTO districtCountDTO, List<String> districtCodeList,
                                  List<String> cameraIdList) {
        if (districtCodeList.contains(districtCountDTO.getCode())) {
            //当前节点被选中，并且需要返回该节点下的 cameraIdList
            return districtCountDTO;
        } else {
            //判断子节点
            List<DistrictCountDTO> children = districtCountDTO.getChildren();
            //返回选中的节点
            List<DistrictCountDTO> filteredChild = new ArrayList<>();
            children.forEach(childDTO -> {
                childDTO = isHit(childDTO, districtCodeList, cameraIdList);
                if (childDTO != null) {
                    filteredChild.add(childDTO);
                }
            });
            //返回选中的节点
            districtCountDTO.setChildren(filteredChild);

            //判断当前节点的监控列表是否被选中
            List<CameraVO> cameraList = districtCountDTO.getCameraList();
            cameraList = cameraList.stream()
                    .filter(cameraVO -> cameraIdList.contains(cameraVO.getId().toString()))
                    .collect(Collectors.toList());
            //将选中的监控列表返回
            districtCountDTO.setCameraList(cameraList);

            //既没有命中区域 也没有命中监控
            if (!CollectionUtils.isEmpty(filteredChild) || !CollectionUtils.isEmpty(cameraList)) {
                return districtCountDTO;
            }
            return null;
        }
    }

    /**
     * 格式化赛达树形数据，赛达返回的数据时行政区域和监控列表都在一起，格式化后需要拆开
     *
     * @param districtTreeVO 赛达树形数据结构
     *
     * @return 格式化后的数据结构 DistrictCountDTO
     */
    public DistrictCountDTO formatSaidaData(SaidaDistrictTreeVO districtTreeVO) {
        List<SaidaDistrictTreeVO> currentChildren = districtTreeVO.getChildren();
        //行政区划列表
        List<DistrictCountDTO> children = new ArrayList<>();
        //监控列表
        List<CameraVO> cameraList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(currentChildren)) {
            //监控列表
            cameraList = currentChildren.stream()
                    .filter(saidaDistrictTreeVO -> saidaDistrictTreeVO.getType() == 2)
                    .filter(saidaDistrictTreeVO -> saidaDistrictTreeVO.getCode() != null)
                    .map(saidaDistrictTreeVO -> {
                        String code = saidaDistrictTreeVO.getCode();
                        String id = saidaDistrictTreeVO.getId();
                        if (StringUtils.isBlank(id)) {
                            id = code;
                            if (code.contains(",")) {
                                id = code.substring(0, code.indexOf(","));
                            }
                        }
                        return CameraVO.builder()
                                .id(Long.parseLong(id))
                                .code(code)
                                .cameraName(saidaDistrictTreeVO.getName())
                                .type(saidaDistrictTreeVO.getCameraType())
                                .cameraType(saidaDistrictTreeVO.getCameraType())
                                .online(saidaDistrictTreeVO.getOnline())
                                .cameraId(saidaDistrictTreeVO.getCode())
                                .build();
                    })
                    .collect(Collectors.toList());

            //监控挂在区、县下面，所以区县是叶子节点了。行政区划编码长度是6，后面的子行政区划直接丢弃
            if (districtTreeVO.getCode().length() < FireConstant.DISTRICT_TOWN_CODE_LENGTH) {
                //行政区划列表
                currentChildren.forEach(saidaDistrictTreeVO -> {
                    if (saidaDistrictTreeVO.getType() == 1) {
                        //递归调用
                        children.add(formatSaidaData(saidaDistrictTreeVO));
                    }
                });
            }
        }

        //返回格式化后的数据结构
        return DistrictCountDTO.builder()
                .id(districtTreeVO.getId() == null ? null : Long.parseLong(districtTreeVO.getId()))
                .name(districtTreeVO.getName())
                .code(districtTreeVO.getCode())
                .parentCode(districtTreeVO.getParentCode())
                .count(districtTreeVO.getNum())
                .children(children)
                .cameraList(cameraList)
                .build();
    }

    /**
     * 行政区划code 映射 监控数量
     *
     * @param child 行政区划、监控集合
     */
    public void putDistrictCode2Num(List<SaidaDistrictTreeVO> child, Map<String, Integer> districtCode2Num) {
        if (!CollectionUtils.isEmpty(child)) {
            child.stream()
                    .filter(saidaDistrictTreeVO -> saidaDistrictTreeVO.getType() == 1)
                    .forEach(saidaDistrictTreeVO -> {
                        if (saidaDistrictTreeVO.getNum() > 0) {
                            districtCode2Num.put(saidaDistrictTreeVO.getCode(), saidaDistrictTreeVO.getNum());
                        }

                        //递归
                        putDistrictCode2Num(saidaDistrictTreeVO.getChildren(), districtCode2Num);
                    });
        }
    }

//    /**
//     * 监控列表查询
//     */
//    @Override
//    public List<CameraVO> pageList(String districtCode, Integer pageNum, Integer pageSize, Integer type, Integer online,
//                                   String cameraName) {
//        DataReturn currentDataReturn = alarmsFeignClient.qryCameraList(pageNum, pageSize, type, online, cameraName,
//                districtCode, null);
//        if (!ResultCode.SUCCESS.getCode().equals(currentDataReturn.getCode())
//                && !FireConstant.ALARMS_SUCCESS_CODE.equals(currentDataReturn.getCode())) {
//            throw new ForestBaseException(currentDataReturn.getErrorMsg());
//        }
//        List<CameraVO> currentList = JSON.parseArray(JSON.toJSONString(currentDataReturn.getData()), CameraVO.class);
//        if (!CollectionUtils.isEmpty(currentList)) {
//            currentList = currentList.stream()
//                    .peek(cameraVO -> {
//                        cameraVO.setCode(String.valueOf(cameraVO.getId()));
//                        cameraVO.setType(cameraVO.getCameraType());
//                    }).collect(Collectors.toList());
//        }
//
//        return currentList;
//    }

//    /**
//     * 查询监控详情
//     */
//    @Override
//    public Object findOne(String id) {
//        DataReturn result = alarmsFeignClient.findOne(id);
//        return result.getData();
//    }

    /**
     * 根据父行政区划编码查询子类数量
     * <p>
     * 监控挂在区、县下面，所以区县是叶子节点了。行政区划编码长度是6
     * </p>
     *
     * @param type         监控类型 1防火监控2防盗监控3卡口监控
     * @param online       在线  1在线 0离线
     * @param cameraName   监控名称（模糊查询）
     * @param districtCode 父行政区划编码
     *
     * @return DistrictCountDTO Obj
     */
    @Override
    public DistrictCountDTO qryNumByParentCode(Integer type, Integer online, String cameraName, String districtCode) {
        LambdaQueryWrapper<CommCameraInfo> commCameraInfoQueryWrapper = new LambdaQueryWrapper<>();
        commCameraInfoQueryWrapper.eq(CommCameraInfo::getPictureType, 0);
        if (type != null) {
            commCameraInfoQueryWrapper.eq(CommCameraInfo::getMonitoringType, String.valueOf(type));
        }
        if (StringUtils.isNotEmpty(cameraName)) {
            commCameraInfoQueryWrapper.like(CommCameraInfo::getName, cameraName);
        }
        if (StringUtils.isNotEmpty(districtCode)) {
            commCameraInfoQueryWrapper.likeRight(CommCameraInfo::getDistrictCode, districtCode);
        }
        Integer count = commCameraInfoDAO.selectCount(commCameraInfoQueryWrapper);

        commCameraInfoQueryWrapper.eq(CommCameraInfo::getDeviceStatus, String.valueOf(0));
        Integer offlineCount = commCameraInfoDAO.selectCount(commCameraInfoQueryWrapper);

        Integer onlineCount = count - offlineCount;
        return DistrictCountDTO.builder()
                .count(count)
                .offlineCount(offlineCount)
                .onlineCount(onlineCount)
                .build();
    }

    /**
     * 分页查询监控列表
     *
     * @param pageNo       当前页数
     * @param pageSize     每页条数
     * @param noPage       是否不分页 true-不分页
     * @param type         监控类型 1防火监控2防盗监控3卡口监控
     * @param online       在线  1在线 0离线
     * @param cameraName   监控名称（模糊查询）
     * @param districtCode 父行政区划编码
     *
     * @return PageData
     */
    @Override
    public PageData<List<CameraVO>> qryListByParentCode(Integer pageNo, Integer pageSize, boolean noPage, Integer type,
                                                        Integer online, String cameraName, String districtCode) {
        if (noPage) {
            pageSize = Integer.MAX_VALUE;
        }

        //查询监控列表
        LambdaQueryWrapper<CommCameraInfo> commCameraInfoQueryWrapper = new LambdaQueryWrapper<>();
        commCameraInfoQueryWrapper.eq(CommCameraInfo::getPictureType, 0);
        if (type != null) {
            commCameraInfoQueryWrapper.eq(CommCameraInfo::getMonitoringType, String.valueOf(type));
        }
        if (online != null) {
            commCameraInfoQueryWrapper.eq(CommCameraInfo::getDeviceStatus, online);
        }
        if (StringUtils.isNotEmpty(cameraName)) {
            commCameraInfoQueryWrapper.like(CommCameraInfo::getName, cameraName);
        }
        if (StringUtils.isNotEmpty(districtCode)) {
            commCameraInfoQueryWrapper.likeRight(CommCameraInfo::getDistrictCode, districtCode);
        }
        IPage<CommCameraInfo> iPage = commCameraInfoDAO.selectPage(new Page<>(pageNo, pageSize),
                commCameraInfoQueryWrapper);
        int count = (int) iPage.getTotal();
        if (count <= 0) {
            return PageData.<List<CameraVO>>builder().count(0).current(pageNo).size(pageSize).datas(
                    new ArrayList<>()).build();
        }
        List<CommCameraInfo> commCameraInfos = iPage.getRecords();
        List<CameraVO> cameraVOS = new ArrayList<>();

        List<CameraVO> finalCurrentList = cameraVOS;
        commCameraInfos.forEach(commCameraInfo -> {
            finalCurrentList.add(CameraVO.builder()
                    .areaCode(commCameraInfo.getDistrictCode())
                    .areaName(commCameraInfo.getDistrictName())
                    .cameraId(commCameraInfo.getCameraIndexCode())  //可见光、热成像
                    .cameraName(commCameraInfo.getName())
                    .cameraRadius(StringUtils.isNotEmpty(commCameraInfo.getMonitoringRadius()) ? new BigDecimal(
                            commCameraInfo.getMonitoringRadius()) : null)
                    .cameraType(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                            commCameraInfo.getMonitoringType()) : null)
                    .code(commCameraInfo.getCameraIndexCode())
                    .id(commCameraInfo.getId())
                    .frameType(commCameraInfo.getPictureType())
                    .isControl(commCameraInfo.getEnableController())
                    .latitude(commCameraInfo.getLatitude())
                    .longitude(commCameraInfo.getLongitude())
                    .online(StringUtils.isNotEmpty(commCameraInfo.getDeviceStatus()) ? Integer.parseInt(
                            commCameraInfo.getDeviceStatus()) : null)
                    .placeName(commCameraInfo.getAddress())
//                            .previewUrl()
                    .type(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                            commCameraInfo.getMonitoringType()) : null)
                    .equipmentType(StringUtils.isNotEmpty(commCameraInfo.getDeviceType()) ? Integer.parseInt(
                            commCameraInfo.getDeviceType()) : null)
                    .token(commCameraInfo.getToken())
                    .build());
        });
        cameraVOS = finalCurrentList;

        return PageData.<List<CameraVO>>builder().count(count).current(pageNo).size(pageSize).datas(cameraVOS).build();
    }

    /**
     * 查询详情
     *
     * @param id id
     *
     * @return CameraVO
     */
    @Override
    public CameraVO info(String id) {
        LambdaQueryWrapper<CommCameraInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CommCameraInfo::getId, Long.parseLong(id));
        CommCameraInfo commCameraInfo = commCameraInfoDAO.selectOne(queryWrapper);
        if (commCameraInfo == null) {
            return null;
        }
        if (commCameraInfo.getPictureType() == 1) {
            LambdaQueryWrapper<CommCameraInfo> commCameraInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
            commCameraInfoLambdaQueryWrapper.eq(CommCameraInfo::getName, commCameraInfo.getName());
            commCameraInfoLambdaQueryWrapper.eq(CommCameraInfo::getPictureType, 0);
            commCameraInfo = commCameraInfoDAO.selectOne(commCameraInfoLambdaQueryWrapper);
        }

        CameraVO cameraVO = CameraVO.builder()
                .areaCode(commCameraInfo.getDistrictCode())
                .areaName(commCameraInfo.getDistrictName())
                .cameraId(commCameraInfo.getCameraIndexCode())  //可见光、热成像
                .cameraName(commCameraInfo.getName())
                .cameraRadius(StringUtils.isNotEmpty(commCameraInfo.getMonitoringRadius()) ? new BigDecimal(
                        commCameraInfo.getMonitoringRadius()) : null)
                .cameraType(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                        commCameraInfo.getMonitoringType()) : null)
                .code(commCameraInfo.getCameraIndexCode())
                .id(commCameraInfo.getId())
                .frameType(commCameraInfo.getPictureType())
                .isControl(commCameraInfo.getEnableController())
                .latitude(commCameraInfo.getLatitude())
                .longitude(commCameraInfo.getLongitude())
                .online(StringUtils.isNotEmpty(commCameraInfo.getDeviceStatus()) ? Integer.parseInt(
                        commCameraInfo.getDeviceStatus()) : null)
                .placeName(commCameraInfo.getAddress())
//                            .previewUrl()
                .type(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                        commCameraInfo.getMonitoringType()) : null)
                .equipmentType(StringUtils.isNotEmpty(commCameraInfo.getDeviceType()) ? Integer.parseInt(
                        commCameraInfo.getDeviceType()) : null)
                .token(commCameraInfo.getToken())
                .build();

        //热成像
        LambdaQueryWrapper<CommCameraInfo> commCameraInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        commCameraInfoLambdaQueryWrapper.eq(CommCameraInfo::getName, cameraVO.getCameraName());
        commCameraInfoLambdaQueryWrapper.eq(CommCameraInfo::getPictureType, 1);
        CommCameraInfo cameraInfo = commCameraInfoDAO.selectOne(commCameraInfoLambdaQueryWrapper);
        if (cameraInfo != null) {
            cameraVO.setCameraId(cameraVO.getCameraId() + "," + cameraInfo.getCameraIndexCode());
            cameraVO.setToken(cameraVO.getToken() + "," + cameraInfo.getToken());
        }

        return cameraVO;
    }

    @Override
    public CameraVO qryInfo(String id, String code) {
        LambdaQueryWrapper<CommCameraInfo> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(id)) {
            queryWrapper.eq(CommCameraInfo::getId, Double.valueOf(id));
        }
        if (StringUtils.isNotEmpty(code)) {
            queryWrapper.eq(CommCameraInfo::getCameraIndexCode, code);
        }
        CommCameraInfo commCameraInfo = commCameraInfoDAO.selectOne(queryWrapper);

        if (commCameraInfo == null) {
            return null;
        }
        CameraVO cameraVO = CameraVO.builder()
                .areaCode(commCameraInfo.getDistrictCode())
                .areaName(commCameraInfo.getDistrictName())
                .cameraId(commCameraInfo.getCameraIndexCode())  //可见光、热成像
                .cameraName(commCameraInfo.getName())
                .cameraRadius(StringUtils.isNotEmpty(commCameraInfo.getMonitoringRadius()) ? new BigDecimal(
                        commCameraInfo.getMonitoringRadius()) : null)
                .cameraType(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                        commCameraInfo.getMonitoringType()) : null)
                .code(commCameraInfo.getCameraIndexCode())
                .id(commCameraInfo.getId())
                .frameType(commCameraInfo.getPictureType())
                .isControl(commCameraInfo.getEnableController())
                .latitude(commCameraInfo.getLatitude())
                .longitude(commCameraInfo.getLongitude())
                .online(StringUtils.isNotEmpty(commCameraInfo.getDeviceStatus()) ? Integer.parseInt(
                        commCameraInfo.getDeviceStatus()) : null)
                .placeName(commCameraInfo.getAddress())
//                            .previewUrl()
                .type(StringUtils.isNotEmpty(commCameraInfo.getMonitoringType()) ? Integer.parseInt(
                        commCameraInfo.getMonitoringType()) : null)
                .equipmentType(StringUtils.isNotEmpty(commCameraInfo.getDeviceType()) ? Integer.parseInt(
                        commCameraInfo.getDeviceType()) : null)
                .token(commCameraInfo.getToken())
                .build();
        //热成像
        LambdaQueryWrapper<CommCameraInfo> commCameraInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        commCameraInfoLambdaQueryWrapper.eq(CommCameraInfo::getName, cameraVO.getCameraName());
        commCameraInfoLambdaQueryWrapper.eq(CommCameraInfo::getPictureType, 1);
        CommCameraInfo cameraInfo = commCameraInfoDAO.selectOne(commCameraInfoLambdaQueryWrapper);
        if (cameraInfo != null) {
            cameraVO.setCameraId(cameraVO.getCameraId() + "," + cameraInfo.getCameraIndexCode());
            cameraVO.setToken(cameraVO.getToken() + "," + cameraInfo.getToken());
        }

        return cameraVO;
    }

    @Override
    public CommCameraInfo queryByCameraIndexCode(String cameraIndexCode) {
        LambdaQueryWrapper<CommCameraInfo> commCameraInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        commCameraInfoLambdaQueryWrapper.eq(CommCameraInfo::getCameraIndexCode, cameraIndexCode);
        CommCameraInfo cameraInfo = commCameraInfoDAO.selectOne(commCameraInfoLambdaQueryWrapper);
        return cameraInfo;
    }

    @Override
    public PageData<Object> listByPage(String districtCode, String monitoringType, String name, Integer current,
                                       Integer size, String deviceStatus) {
        if (districtCode != null && !"".equals(districtCode)) {
            districtCode = "%" + districtCode + "%";
        }
        if (name != null && !"".equals(name)) {
            name = "%" + name + "%";
        }
        IPage<CommCameraInfo> iPage = new Page<>(current, size);
        //查询出所有可见光设备
        IPage<CommCameraInfo> pages = commCameraInfoDAO.selectByPage(iPage, districtCode, monitoringType, name,
                deviceStatus);
        List<CommCameraInfo> records = pages.getRecords();
        //如果有热成像设备就赋值给该对象
        records.forEach(e -> {
            VisibleLightInfoDTO visibleLightInfoDTO = new VisibleLightInfoDTO();
            BeanUtils.copyProperties(e, visibleLightInfoDTO);
            e.setVisibleLightInfoDTO(visibleLightInfoDTO);
            String cameraName = e.getName();
            CommCameraInfo commCameraInfo = commCameraInfoDAO.queryByNameAndType(cameraName, e.getMonitoringType(), 1,
                    deviceStatus, e.getDistrictCode());
            ThermalImagingInfoDTO thermalImagingInfoDTO = new ThermalImagingInfoDTO();
            if (commCameraInfo != null) {
                BeanUtils.copyProperties(commCameraInfo, thermalImagingInfoDTO);
            }
            e.setThermalImagingInfoDTO(thermalImagingInfoDTO);
        });

        PageData<Object> pageData = new PageData<>();
        pageData.setDatas(records);
        pageData.setCount((int) pages.getTotal());
        pageData.setCurrent((int) pages.getCurrent());
        pageData.setSize((int) pages.getSize());
        return pageData;
    }

    @Override
    public int countCamera(String districtCode, String type,String deviceStatus) {
        if (StringUtils.isNotBlank(districtCode)){
            districtCode=districtCode+"%";
        }
        int countCamera = commCameraInfoDAO.countCamera(districtCode, type,deviceStatus);
        return countCamera;
    }


    @Override
  //  @Cacheable(value = "firecommand:camera:queryListByPoint",depict = "根据火点位置查询可视域范围内的监控")
    public List<CameraFirePointDTO> queryListByPoint(String firePoint, Long fireId, String districtCode) {
//        if(fireId !=null && fireId !=0L){
//            return commCameraInfoDAO.queryCameraInfoByFireId(fireId);
//        }
        CommCameraInfo cameraInfo = null;
        if (fireId != null) {
            CommFireAlarm commFireAlarm = commFireAlarmDao.selectByPrimaryKey(fireId);
            if (commFireAlarm.getResource().equals("3")) {
                Long deviceId = commFireAlarm.getDeviceId();
                cameraInfo = commCameraInfoDAO.selectById(deviceId);
            }
        }
        List<CameraFirePointDTO> cameraFirePointDTOS = new ArrayList<>();
        try {
//            cameraFirePointDTOS = commCameraInfoDAO.queryListByPoint(firePoint, districtCode);
            //将 + 转成 空格
            firePoint = firePoint.replace("+", " ");
            List<CommCameraInfo> commCameraInfoList = fireCameraDAO.qryCameraListByPoint(districtCode, firePoint, null,
                    0, null);
            cameraFirePointDTOS = commCameraInfoList.stream()
                    .map(commCameraInfo -> Convert.convert(CameraFirePointDTO.class, commCameraInfo))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (cameraInfo != null) {
            Long id = cameraInfo.getId();
            boolean exists = cameraFirePointDTOS.stream().anyMatch(element -> element.getId().compareTo(id) == 0);
            if (!exists) {
                cameraFirePointDTOS.add(Convert.convert(CameraFirePointDTO.class, cameraInfo));
            }
        }
        return cameraFirePointDTOS;
    }



    @Override
    public List<CommCameraInfo> queryByCondition(String keyWord, String deviceStatus,String monitoringType,String districtCode) {
       /* if (keyWord !=null && !"".equals(keyWord)){
            keyWord="%"+keyWord+"%";
        }*/
        List<CommCameraInfo> cameraInfoList=commCameraInfoDAO.queryByCondition(keyWord,deviceStatus,monitoringType,districtCode);
        setDistrictName(cameraInfoList,geoXzqhCunDao);
        return cameraInfoList;
    }

    @Override
    public void updateCameraOnlineInfo() {
        List<CommCameraInfo> list = commCameraInfoDAO.selectList(new QueryWrapper<>());
        list.forEach(commCameraInfo -> {
            if(StringUtils.isNotEmpty(commCameraInfo.getIp())) {
                try {
                    //ip是通的，则为在线
                    if(isNodeReachable(commCameraInfo.getIp())) {
                        commCameraInfoDAO.updateStatusById(commCameraInfo.getId(), "1");
                    } else {
                        commCameraInfoDAO.updateStatusById(commCameraInfo.getId(), "0");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                commCameraInfoDAO.updateStatusById(commCameraInfo.getId(), "0");
            }
        });
    }

    private boolean isNodeReachable(String ip) {
        try {
            InetAddress geek = InetAddress.getByName(ip);
            return geek.isReachable(3000);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    public static void setDistrictName(List<CommCameraInfo> list, GeoXzqhCunDao geoXzqhCunDao){
        list.forEach(e->{
            String districtCode = e.getDistrictCode();
            String name = geoXzqhCunDao.queryDistrictNameByCode(districtCode,districtCode.length());
            if (name!=null){
                e.setDistrictName(name);
            }
        });
    }

}
